
var common = require("./common") 
var db = require("./db");
var kurento = require('kurento-client');

class TVSportApp{
    constructor(){
        this.code = "";
        this.info={};
        this.objs ={};
        this.pipe = null;
        this.hub= null;
        this.devs = {};
        this.ports = {};
        this.OutPorts ={};
    }
}
class TVSport{
    constructor(){
        this.config={
            db:{
                dbKey:'vSport',
                dbInfo:{
                    host:"tjiot.hhdata.cn" ,
                    port:53306,
                    uid:"root",
                    pwd:"hhuc1115",
                    db:"vSport" ,
                    sqlPath:"D:/gitee/vsport/vsport/web/sqls"
                }
            },
            kms:{
                //kmsUrl:"wss://ssl.hhdata.cn:40014/kurento" ,
                kmsUrl: "wss://wss.hhdata.cn:8433/kurento",
                appPipeName :"vSportPipe",
                infoKey:"hhucKmsInfo"
            }
        },
        this.db = new db.TDBMySql();
        this.kmsClient = null;
        this.objs = {};
        this.apps={};
    }
    loadObjsFromDB( client ){
        var me = this;
        return new Promise((success,faild)=>{
            try{
                me.db.setConfig( me.config.db.dbKey , me.config.db.dbInfo);
                var sql ="select * from T_Obj";
                me.db.query( me.config.db.dbKey , sql , {} , function(res){
                    var items = res.result;
                    var releaseItemIds =[]
                    var loadItem = function(){
                        if( items.length>0){
                            var item = items.shift();
                            client.getMediaobjectById( item.kmsId, function(erf, obj){
                                if( !erf && obj &&  obj!=null){
                                    obj.info = item;
                                    me.objs[item.kmsId] = obj;
                                    var app = me.apps[item.app];
                                    if( !app ){
                                        app = new TVSportApp();
                                        app.code = item.app;
                                        app.info = item;
                                        me.apps[item.app] = app;
                                    }                                    
                                    app.objs[item.code] = obj;
                                    if( item.objType == 'pipe'){
                                        app.pipe = obj;
                                    }
                                    else if( item.objType == 'hub'){
                                        app.hub = obj;
                                    }
                                    else if( item.objType == 'dev'){
                                        app.devs[item.code] = obj;
                                    }
                                    else if( item.objType == 'appPort'){
                                        app.ports[item.code] = obj;
                                    }
                                }
                                else{
                                    releaseItemIds.push(item.objId);
                                }
                                loadItem();
                            })
                        }
                        else{
                            if( releaseItemIds.length==0){
                                success();
                            }
                            else{
                                sql = 'delete from T_Obj where objId in ( '+ releaseItemIds.join(',')+")" ;
                                me.db.query( me.config.db.dbKey , sql , {} , function(resRelease){
                                    success();
                                });
                            }
                        }
                    }
                    loadItem();
                });
            }
            catch(er){
                console.log(er);
                success();
            }
        })
    }
    getClient( ){
        var me = this;
        return new Promise((success,faild)=>{
            try{
                if( common.TComm.isnull(me.kmsClient)){
                    console.log(me.config.kms.kmsUrl);
                    kurento( me.config.kms.kmsUrl).then(client=>{
                        me.kmsClient = client;
                        me.loadObjsFromDB( client ).then(()=>{
                            success(client);
                        });
                    })
                }
                else{
                    success(me.kmsClient);
                }
            }
            catch(er){
                console.log(er);
                success();
            }
        })
    }
    registObj( obj , app , objType , code , clientId ){
        var me = this;
        return new Promise((success,faild)=>{
            try{
                var sql = 'DELETE FROM T_Obj WHERE app=:app AND `code`=:code;INSERT INTO T_Obj(app,`code`,objType,kmsId,clientId) values (:app, :code, :objType , :kmsId, :clientId);';
                var ps ={
                    app:app ,
                    code: code ,
                    objType: objType ,
                    kmsId: obj.id ,
                    clientId:clientId
                };
                me.db.query(me.config.db.dbKey , sql , ps , function(res){
                    if( res.result && res.result.length>1 && res.result[1] && res.result[1].insertId>0){
                        ps.objId = res.result[1].insertId;
                        obj.info = ps;
                        me.objs[ps.kmsId] = obj;
                        var app = me.apps[ps.app];           
                        app.objs[code] = obj;
                        if( objType == 'pipe'){
                            app.pipe = obj;
                        }
                        else if( objType == 'hub'){
                            app.hub = obj;
                        }
                        else if( objType == 'dev'){
                            app.devs[code] = obj;
                        }
                        else if( objType == 'appPort'){
                            app.ports[code] = obj;
                        }
                        obj.addTag(me.config.kms.infoKey , JSON.stringify(ps)).then(()=>{
                            success(obj);
                        });
                    }
                })
            }
            catch(er){
                console.log(er);
                success();
            }
        })
    } 
    loadApp( appCode , client ){
        var me = this;
        return new Promise((success,faild)=>{
            try{
                var sql =[
                    "select * from T_App where appCode=:appCode" ,
                    "SELECT d.* , a.appCode , a.appName FROM T_Dev d JOIN T_App a ON a.appId = d.appId where a.appCode=:appCode and d.devType = 'd'" ,
                    "SELECT d.* , a.appCode , a.appName FROM T_Dev d JOIN T_App a ON a.appId = d.appId where a.appCode=:appCode " 
                ].join(";");
                var ps={
                    appCode: appCode
                }
                me.db.query( me.config.db.dbKey , sql , ps , function(res){
                    console.log(res);
                    var appCode = res.result[0][0].appCode;
                    var devs = res.result[1];
                    var ports = res.result[2];
                    var loadPipe = function(onLoad){
                        try{
                            if( app.pipe==null){
                                client.create("MediaPipeline").then(pipe=>{
                                    me.registObj(pipe , appCode , 'pipe' ,'pipe' , 'common').then(()=>{
                                        onLoad();
                                    });
                                })
                            }
                            else{
                                onLoad();
                            }
                        }
                        catch(eer){
                            onLoad();
                        }
                    }
                    
                    var loadHub = function(suc){
                        try{
                            if( app.hub==null){
                                app.pipe.create("Dispatcher").then(hub=>{
                                    me.registObj(hub , appCode , 'hub' ,'hub' , 'common').then(()=>{
                                        suc();
                                    });
                                })
                            }
                            else{
                                suc();
                            }
                        }
                        catch(eer){
                            suc();
                        }
                    }
                    var loadDevs = function(suc){
                        try{
                            var loadItem = function(){
                                if( devs.length>0){
                                    var dev = devs.shift();
                                    var devCode = 'dev-'+ dev.devCode;
                                    if( app.devs[devCode] ){
                                        var devEnd = app.devs[devCode];
                                        devEnd.getState().then(state=>{
                                            if( state=="STOP"){
                                                devEnd.play(function(erPlay){
                                                    loadItem();
                                                })
                                            }
                                            else{
                                                loadItem();
                                            }
                                        })
                                    }
                                    else{
                                        app.pipe.create("PlayerEndpoint", {uri: dev.devUrl}).then(devEnd=>{          
                                            devEnd.on("EndOfStream" , function(){
                                                devEnd.play();
                                            });
                                            devEnd.play(function(erPlay){
                                                me.registObj(devEnd , appCode , 'dev' , devCode , 'common').then(()=>{
                                                    app.devs[devCode] = devEnd;
                                                    loadItem();
                                                });
                                            })
                                        })
                                    }
                                }
                                else{
                                    suc();
                                }
                            }
                            loadItem();
                        }
                        catch(eer){
                            suc();
                        }
                    }
                    var loadPorts = function(suc){
                        try{
                            var loadItem = function(){
                                if( ports.length>0){
                                    var port = ports.shift();
                                    var portCode = 'appPort-'+ port.devCode;
                                    if( app.ports[portCode] ){
                                        loadItem();
                                    }
                                    else{
                                        app.hub.createHubPort().then(hubPort=>{                                            
                                            me.registObj(hubPort , appCode , 'appPort' , portCode , 'common').then(()=>{
                                                app.ports[portCode] = hubPort;
                                                if( port.devType=='d'){
                                                    var devCode = 'dev-'+ port.devCode;
                                                    var devEnd = app.devs[devCode];
                                                    if( devEnd){
                                                        devEnd.connect(hubPort).then(()=>{
                                                            loadItem();
                                                        })
                                                    }
                                                    else{
                                                        loadItem();
                                                    }
                                                }
                                                else{
                                                    loadItem();
                                                }
                                            });
                                        })
                                    }
                                }
                                else{
                                    suc();
                                }
                            }
                            loadItem();
                        }
                        catch(eer){
                            suc();
                        }
                    }
                    var app = me.apps[appCode];
                    if(!app){
                        app = new TVSportApp();
                        app.code = appCode;
                        me.apps[appCode] = app;
                    }
                    loadPipe(function(){
                        loadHub(function(){
                            loadDevs(function(){
                                loadPorts(function(){
                                    success();
                                })
                            })
                        })
                    })
                    
                });
            }
            catch(er){
                console.log(er);
                success();
            }
        })
    }
    getAppInfo( app  ){
        var me = this;
        var res = {};
        try{ 
            res.pipeInfo = app.pipe.info ;
            res.hubInfo = app.hub.info ;            
            res.devs = {};
            res.ports = {};
            Object.keys(app.devs).forEach(key=>{
                res.devs[key] = app.devs[key].info;
            })
            Object.keys(app.ports).forEach(key=>{
                res.ports[key] = app.ports[key].info;
            })
            
        }
        catch(er){
            console.log(er); 
        }
        return res;
    }
    createSession(   appCode , code , clientId , pushPortCode , pullPortCode  ){
        var me = this;
        var res = {
            state:0 ,
            end:null ,
            pullPort: null
        };
        var me = this;
        return new Promise((success,faild)=>{
            try{
                var app = me.apps[appCode];
                if( app ){  
                    app.pipe.create("WebRtcEndpoint").then(end=>{
                        return me.registObj(end , appCode , "sessionEnd" , code , clientId)
                    }).then(end=>{
                        var connectAppPort = function(onConnect){
                            var flag =  pushPortCode && pushPortCode!=null && pushPortCode!="" && app.ports[pushPortCode];
                            if( flag){
                                var port = app.ports[pushPortCode];
                                end.connect(port, function(erConn){
                                    onConnect();
                                })
                            }
                            else{
                                onConnect();
                            }
                        }
                        var connectPullPort = function(onConnect){
                            var flag =  pullPortCode && pullPortCode!=null && pullPortCode!="" && app.ports[pullPortCode];
                            if( flag){ 
                                app.hub.createHubPort().then(pullPort=>{
                                    me.registObj( pullPort , appCode , "sessionPullPort" , code , clientId).then(pullPort=>{
                                        var srcPort = app.ports[pullPortCode];
                                        app.hub.connect(srcPort , pullPort, function(erConn){
                                            pullPort.connect(end, function(erCo1){
                                                res.pullPortInfo = pullPort.info;
                                                onConnect();
                                            })
                                        })
                                    })
                                })
                            }
                            else{
                                onConnect();
                            }
                        }
                        res.endInfo = end.info;
                        connectAppPort(function(){
                            connectPullPort(function(){
                                success(res);
                            })
                        })
                    })
                    
                }
                else{
                    success();
                }
            }
            catch(er){
                console.log(er);
                success();
            }
        }) 
    }
    regist2WebSvr(webSvr){
        var me = this;
        if( webSvr && webSvr!=null){
            var respJson = function(result , response){
                try{
                    response.send(JSON.stringify(result));
                }
                catch(eer){
                    console.log(eer);
                }
            }
            webSvr.registRoute ( "vsport" , "app" , "loadApp" , function( result , request , response ){                
                try{
                    var appCode = result.ps.appCode ;  
                    me.getClient().then(client=>{
                        me.loadApp(appCode , client).then((res)=>{
                            var app = me.apps[appCode];
                            result.data = me.getAppInfo(app);
                            respJson(result, response);
                        });
                    })
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
            }); 
            webSvr.registRoute ( "vsport" , "app" , "createSession" , function( result , request , response ){                
                try{
                    var appCode = result.ps.appCode ; 
                    var code = result.ps.code ; 
                    var clientId = result.ps.clientId ; 
                    var pushPortCode = result.ps.pushPortCode ; 
                    var pullPortCode = result.ps.pullPortCode ;  
                    me.createSession(   appCode , code , clientId , pushPortCode , pullPortCode  ).then((res)=>{                        
                        result.data = res;
                        respJson(result, response);
                    });
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
            }); 
            webSvr.registRoute ( "vsport" , "app" , "registObj" , function( result , request , response ){                
                try{
                    var appCode = result.ps.appCode ; 
                    var code = result.ps.code ; 
                    var clientId = result.ps.clientId ; 
                    var objType = result.ps.objType ; 
                    var kmsId = result.ps.kmsId ;  
                    me.getClient().then(client=>{
                        client.getMediaobjectById(kmsId, function(ero, obj){
                            if( obj && obj!=null){
                                me.registObj(obj , appCode , objType , code , clientId).then(regObj=>{
                                    result.data = regObj.info;
                                    respJson(result, response);
                                })
                            }
                            else{                  
                                result.error ="kmsId is error.";
                                result.data = {};
                                respJson(result, response);
                            }
                        });
                    })

                    me.createSession(   appCode , code , clientId , pushPortCode , pullPortCode  ).then((res)=>{                        
                        result.data = res;
                        respJson(result, response);
                    });
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
            }); 
            webSvr.registRoute ( "vsport" , "app" , "connectHubPort" , function( result , request , response ){                
                try{
                    var srcId = result.ps.srcId ; 
                    var tarId = result.ps.tarId ; 
                    var arr = srcId.split("/");
                    var hubId = arr.length>2? arr[0] +'/'+ arr[1]:"";
                    var src = null;
                    var tar = null;
                    var hub = null;
                    me.getClient().then(client=>{
                        client.getMediaobjectById(srcId, function(ero, obj){
                            src = obj;
                            client.getMediaobjectById(tarId, function(ero, obj){
                                tar = obj;                                        
                                client.getMediaobjectById(hubId, function(ero, obj){
                                    hub = obj;
                                    onGetObj();
                                });
                            });
                        });
                    })
                    var onGetObj = function(){
                        var state =0;
                        var msg = "";
                        if( src==null){
                            state = -1;
                        }
                        else if( tar==null){
                            state = -2;
                        }
                        else if( hub==null){
                            state = -3;
                        }
                        else{
                            hub.connect(src , tar , function(erConn){ 
                                state = erConn==null?1:0;
                                result.data = {
                                    state:state ,
                                    errMsg:erConn
                                }
                                response.send(JSON.stringify(result));
                            })
                        }
                    }
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
            }); 
        }
    }
}


module.exports = {
    TVSportApp : TVSportApp ,
    TVSport : TVSport
}
